#!/usr/bin/env python3
"""
配置数据导入脚本
从现有的 .env 文件导入配置数据到数据库
"""

import os
import sys
import asyncio
import logging
import json
from pathlib import Path
from typing import Dict, Any, List, Optional
from dotenv import load_dotenv

# 添加项目根目录到Python路径
project_root = Path(__file__).parent.parent
sys.path.insert(0, str(project_root))

from core.config import ConfigManager
from data_models.Config import ConfigGroup, ConfigItem
from config import Config

# 配置日志
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger(__name__)


class ConfigImporter:
    """配置导入器"""

    def __init__(self):
        self.config_mappings = self._get_config_mappings()
        self.processed_keys = set()

    def _get_config_mappings(self) -> Dict[str, Dict[str, Any]]:
        """
        定义 .env 键名到数据库配置的映射
        """
        return {
            # 服务器配置
            'HOST': {
                'group': 'server',
                'category': 'network',
                'display_name': '服务监听地址',
                'description': 'API服务器监听的IP地址，0.0.0.0表示监听所有网络接口',
                'data_type': 'string',
                'validation_rule': r'^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$|0\.0\.0\.0|localhost$',
                'is_reload_required': True
            },
            'PORT': {
                'group': 'server',
                'category': 'network',
                'display_name': '服务端口',
                'description': 'API服务器监听端口号',
                'data_type': 'integer',
                'value_range': json.dumps({'min': 1024, 'max': 65535}),
                'is_reload_required': True
            },
            'PREVIEW_MODE': {
                'group': 'server',
                'category': 'feature',
                'display_name': '预览模式',
                'description': '是否启用预览模式，大模型响应内容需要人为确认',
                'data_type': 'boolean',
                'is_reload_required': False
            },
            'PREVIEW_TIMEOUT': {
                'group': 'server',
                'category': 'feature',
                'display_name': '预览超时时间',
                'description': '预览超时时间（秒），默认1分钟',
                'data_type': 'integer',
                'value_range': json.dumps({'min': 10, 'max': 300}),
                'is_reload_required': False
            },
            'DELAY_MODE': {
                'group': 'server',
                'category': 'feature',
                'display_name': '延迟模式',
                'description': '是否启用延迟模式，系统会累积用户消息并延迟处理',
                'data_type': 'boolean',
                'is_reload_required': False
            },
            'DELAY_TIME': {
                'group': 'server',
                'category': 'feature',
                'display_name': '延迟处理时间',
                'description': '延迟处理时间（秒），用户停止发送消息超过此时间才处理',
                'data_type': 'integer',
                'value_range': json.dumps({'min': 1, 'max': 60}),
                'is_reload_required': False
            },
            'KNOWLEDGE_BASE_ENABLED': {
                'group': 'server',
                'category': 'feature',
                'display_name': '启用知识库',
                'description': '是否启用知识库，启用后会根据用户问题从知识库中提取相关内容',
                'data_type': 'boolean',
                'is_reload_required': False
            },
            'MCP_PORT': {
                'group': 'server',
                'category': 'mcp',
                'display_name': 'MCP服务端口',
                'description': 'MCP服务端口号',
                'data_type': 'integer',
                'value_range': json.dumps({'min': 1024, 'max': 65535}),
                'is_reload_required': True
            },
            'MCP_TRANSPORT': {
                'group': 'server',
                'category': 'mcp',
                'display_name': 'MCP传输协议',
                'description': 'MCP传输协议类型',
                'data_type': 'string',
                'value_range': json.dumps(['sse', 'stdio']),
                'is_reload_required': True
            },

            # 认证与会话配置
            'API_KEY': {
                'group': 'auth',
                'category': 'security',
                'display_name': 'API密钥',
                'description': 'API访问密钥，为空表示不需要认证',
                'data_type': 'string',
                'is_sensitive': True,
                'is_reload_required': False
            },
            'SESSION_MAX_AGE': {
                'group': 'auth',
                'category': 'session',
                'display_name': '会话有效期',
                'description': '会话有效期，单位为秒，默认为30分钟',
                'data_type': 'integer',
                'value_range': json.dumps({'min': 60, 'max': 86400}),
                'is_reload_required': False
            },
            'MAX_CONVERSATION_MESSAGES': {
                'group': 'auth',
                'category': 'session',
                'display_name': '最大对话消息数',
                'description': '最大对话轮次（消息数量）',
                'data_type': 'integer',
                'value_range': json.dumps({'min': 5, 'max': 100}),
                'is_reload_required': False
            },
            'MAX_CONVERSATION_TOKENS': {
                'group': 'auth',
                'category': 'session',
                'display_name': '最大对话Token数',
                'description': '最大对话token数估算',
                'data_type': 'integer',
                'value_range': json.dumps({'min': 1000, 'max': 32000}),
                'is_reload_required': False
            },
            'ENABLE_CONVERSATION_TRUNCATION': {
                'group': 'auth',
                'category': 'session',
                'display_name': '启用对话截断',
                'description': '是否启用对话截断',
                'data_type': 'boolean',
                'is_reload_required': False
            },

            # 模型配置 - 按需加载开关
            'LLM_MODEL_ENABLED': {
                'group': 'model',
                'category': 'llm',
                'display_name': '启用LLM模型',
                'description': '是否启用本地大语言模型',
                'data_type': 'boolean',
                'is_reload_required': True
            },
            'ASR_MODEL_ENABLED': {
                'group': 'model',
                'category': 'asr',
                'display_name': '启用ASR模型',
                'description': '是否启用语音识别模型',
                'data_type': 'boolean',
                'is_reload_required': True
            },
            'INDEX_TTS_MODEL_ENABLED': {
                'group': 'model',
                'category': 'tts',
                'display_name': '启用IndexTTS模型',
                'description': '是否启用IndexTTS-1.5本地TTS模型',
                'data_type': 'boolean',
                'is_reload_required': True
            },
            'RERANK_MODEL_ENABLED': {
                'group': 'model',
                'category': 'rerank',
                'display_name': '启用Rerank模型',
                'description': '是否启用文档重排序模型',
                'data_type': 'boolean',
                'is_reload_required': True
            },
            'EMBEDDING_MODEL_ENABLED': {
                'group': 'model',
                'category': 'embedding',
                'display_name': '启用Embedding模型',
                'description': '是否启用文本嵌入模型',
                'data_type': 'boolean',
                'is_reload_required': True
            },
            'EDGE_TTS_ENABLED': {
                'group': 'model',
                'category': 'tts',
                'display_name': '启用Edge TTS',
                'description': '是否启用微软Edge TTS云服务',
                'data_type': 'boolean',
                'is_reload_required': False
            },

            # 模型路径配置
            'LLM_MODEL_DIR': {
                'group': 'model',
                'category': 'llm',
                'display_name': 'LLM模型路径',
                'description': '本地大语言模型文件路径',
                'data_type': 'path',
                'is_reload_required': True,
                'placeholder': '/path/to/llm/model'
            },
            'ASR_MODEL_DIR': {
                'group': 'model',
                'category': 'asr',
                'display_name': 'ASR模型路径',
                'description': '语音识别模型文件路径',
                'data_type': 'path',
                'is_reload_required': True,
                'placeholder': '/path/to/asr/model'
            },
            'INDEX_TTS_MODEL_DIR': {
                'group': 'model',
                'category': 'tts',
                'display_name': 'IndexTTS模型路径',
                'description': 'IndexTTS-1.5模型文件路径',
                'data_type': 'path',
                'is_reload_required': True,
                'placeholder': '/path/to/tts/model'
            },
            'RERANK_MODEL_DIR': {
                'group': 'model',
                'category': 'rerank',
                'display_name': 'Rerank模型路径',
                'description': '文档重排序模型文件路径',
                'data_type': 'path',
                'is_reload_required': True,
                'placeholder': '/path/to/rerank/model'
            },
            'EMBEDDING_MODEL_DIR': {
                'group': 'model',
                'category': 'embedding',
                'display_name': 'Embedding模型路径',
                'description': '文本嵌入模型文件路径',
                'data_type': 'path',
                'is_reload_required': True,
                'placeholder': '/path/to/embedding/model'
            },
            'ANY4DH_WAV2LIP_MODEL_DIR': {
                'group': 'digital_human',
                'category': 'model',
                'display_name': 'Wav2Lip模型路径',
                'description': '唇形同步模型文件路径',
                'data_type': 'path',
                'is_reload_required': True,
                'placeholder': '/path/to/wav2lip/model'
            },

            # LLM模型参数配置
            'LLM_MODEL_NAME': {
                'group': 'model',
                'category': 'llm',
                'display_name': 'LLM模型名称',
                'description': '本地大语言模型名称',
                'data_type': 'string',
                'is_reload_required': True
            },
            'MAX_LENGTH': {
                'group': 'model',
                'category': 'llm',
                'display_name': '最大生成长度',
                'description': '本地LLM最大生成长度',
                'data_type': 'integer',
                'value_range': json.dumps({'min': 512, 'max': 8192}),
                'is_reload_required': False
            },
            'TEMPERATURE': {
                'group': 'model',
                'category': 'llm',
                'display_name': '温度参数',
                'description': '控制生成的随机性，0-2之间，越高越随机',
                'data_type': 'float',
                'value_range': json.dumps({'min': 0.0, 'max': 2.0}),
                'is_reload_required': False
            },
            'TOP_P': {
                'group': 'model',
                'category': 'llm',
                'display_name': 'Top-P采样',
                'description': '控制生成的多样性，0-1之间',
                'data_type': 'float',
                'value_range': json.dumps({'min': 0.0, 'max': 1.0}),
                'is_reload_required': False
            },
            'REPETITION_PENALTY': {
                'group': 'model',
                'category': 'llm',
                'display_name': '重复惩罚',
                'description': '控制生成内容的重复程度，大于1减少重复',
                'data_type': 'float',
                'value_range': json.dumps({'min': 0.8, 'max': 2.0}),
                'is_reload_required': False
            },
            'NO_THINK': {
                'group': 'model',
                'category': 'llm',
                'display_name': '禁用思考模式',
                'description': '是否禁用模型的思考过程输出',
                'data_type': 'boolean',
                'is_reload_required': False
            },
            'ASR_PROMPT': {
                'group': 'model',
                'category': 'asr',
                'display_name': 'ASR模型提示词',
                'description': '语音识别模型的提示词',
                'data_type': 'string',
                'is_reload_required': False
            },
            'LLM_PROMPT': {
                'group': 'model',
                'category': 'llm',
                'display_name': 'LLM系统提示词',
                'description': '大语言模型的系统提示词',
                'data_type': 'string',
                'is_reload_required': False
            },

            # LLM模型加载配置
            'TRUST_REMOTE_CODE': {
                'group': 'model',
                'category': 'llm',
                'display_name': '信任远程代码',
                'description': '是否信任远程代码',
                'data_type': 'boolean',
                'is_reload_required': True
            },
            'USE_HALF_PRECISION': {
                'group': 'model',
                'category': 'llm',
                'display_name': '使用半精度',
                'description': '是否使用半精度',
                'data_type': 'boolean',
                'is_reload_required': True
            },
            'LOW_CPU_MEM_USAGE': {
                'group': 'model',
                'category': 'llm',
                'display_name': '低CPU内存使用',
                'description': '是否使用低CPU内存',
                'data_type': 'boolean',
                'is_reload_required': True
            },
            'TOKENIZERS_PARALLELISM': {
                'group': 'model',
                'category': 'llm',
                'display_name': '分词器并行',
                'description': '是否启用多线程分词',
                'data_type': 'boolean',
                'is_reload_required': True
            },

            # 外部LLM API配置
            'LLM_SERVER_TYPE': {
                'group': 'model',
                'category': 'external',
                'display_name': 'LLM服务器类型',
                'description': 'LLM服务器类型：local（本地）或api（外部API）',
                'data_type': 'string',
                'value_range': json.dumps(['local', 'api']),
                'is_reload_required': True
            },
            'EXTERNAL_API_KEY': {
                'group': 'model',
                'category': 'external',
                'display_name': '外部API密钥',
                'description': '外部LLM API密钥',
                'data_type': 'secret',
                'is_sensitive': True,
                'is_reload_required': False
            },
            'API_BASE_URL': {
                'group': 'model',
                'category': 'external',
                'display_name': 'API基础地址',
                'description': '外部API基础地址',
                'data_type': 'string',
                'validation_rule': r'^https?://[^\s/$.?#].[^\s]*$',
                'is_reload_required': False
            },
            'MODEL_NAME': {
                'group': 'model',
                'category': 'external',
                'display_name': '外部API模型名称',
                'description': '外部API模型名称',
                'data_type': 'string',
                'is_reload_required': False
            },
            'API_TIMEOUT': {
                'group': 'model',
                'category': 'external',
                'display_name': 'API超时时间',
                'description': 'API请求超时时间（秒）',
                'data_type': 'integer',
                'value_range': json.dumps({'min': 30, 'max': 600}),
                'is_reload_required': False
            },
            'MAX_TOKENS': {
                'group': 'model',
                'category': 'external',
                'display_name': 'API最大Token数',
                'description': 'API请求最大Token数',
                'data_type': 'integer',
                'value_range': json.dumps({'min': 512, 'max': 128000}),
                'is_reload_required': False
            },
            'STREAM_ENABLED': {
                'group': 'model',
                'category': 'external',
                'display_name': '启用流式输出',
                'description': '外部API是否启用流式输出',
                'data_type': 'boolean',
                'is_reload_required': False
            },
            'API_MAX_RETRIES': {
                'group': 'model',
                'category': 'external',
                'display_name': 'API最大重试次数',
                'description': 'API请求最大重试次数',
                'data_type': 'integer',
                'value_range': json.dumps({'min': 0, 'max': 10}),
                'is_reload_required': False
            },
            'API_RETRY_DELAY': {
                'group': 'model',
                'category': 'external',
                'display_name': 'API重试延迟',
                'description': 'API请求重试延迟（秒）',
                'data_type': 'float',
                'value_range': json.dumps({'min': 0.1, 'max': 10.0}),
                'is_reload_required': False
            },

            # EMBEDDING模型配置
            'TOP_K': {
                'group': 'model',
                'category': 'embedding',
                'display_name': 'Top-K检索数量',
                'description': '取前k个最相似的向量',
                'data_type': 'integer',
                'value_range': json.dumps({'min': 1, 'max': 50}),
                'is_reload_required': False
            },
            'VECTOR_DB_PATH': {
                'group': 'model',
                'category': 'embedding',
                'display_name': '向量数据库路径',
                'description': '向量数据库存储路径',
                'data_type': 'path',
                'is_reload_required': True
            },
            'DOCS_PATH': {
                'group': 'model',
                'category': 'embedding',
                'display_name': '文档路径',
                'description': '知识库文档存储路径',
                'data_type': 'path',
                'is_reload_required': True
            },
            'DOC_CHUNK_SIZE': {
                'group': 'model',
                'category': 'embedding',
                'display_name': '文档分块大小',
                'description': '文档处理器文本分块大小',
                'data_type': 'integer',
                'value_range': json.dumps({'min': 100, 'max': 2000}),
                'is_reload_required': False
            },
            'DOC_CHUNK_OVERLAP': {
                'group': 'model',
                'category': 'embedding',
                'display_name': '文档分块重叠',
                'description': '文档处理器文本分块重叠大小',
                'data_type': 'integer',
                'value_range': json.dumps({'min': 0, 'max': 500}),
                'is_reload_required': False
            },
            'SUPPORTED_FILE_TYPES': {
                'group': 'model',
                'category': 'embedding',
                'display_name': '支持的文件类型',
                'description': '知识库支持的文件类型',
                'data_type': 'json',
                'value_range': json.dumps(['.pdf', '.docx', '.txt', '.md']),
                'is_reload_required': False
            },

            # RERANK模型配置
            'RERANK_CANDIDATE_FACTOR': {
                'group': 'model',
                'category': 'rerank',
                'display_name': '重排序候选倍数',
                'description': '重排序候选文档倍数',
                'data_type': 'integer',
                'value_range': json.dumps({'min': 2, 'max': 50}),
                'is_reload_required': False
            },
            'RERANK_BATCH_SIZE': {
                'group': 'model',
                'category': 'rerank',
                'display_name': '重排序批处理大小',
                'description': '重排序批处理大小',
                'data_type': 'integer',
                'value_range': json.dumps({'min': 1, 'max': 64}),
                'is_reload_required': False
            },

            # IndexTTS-1.5引擎配置
            'INDEX_TTS_FAST_ENABLED': {
                'group': 'model',
                'category': 'tts',
                'display_name': 'IndexTTS快速模式',
                'description': '是否启用IndexTTS-1.5快速推理模式',
                'data_type': 'boolean',
                'is_reload_required': False
            },
            'INDEX_TTS_FAST_MAX_TOKENS': {
                'group': 'model',
                'category': 'tts',
                'display_name': '快速模式最大Token数',
                'description': '快速模式分句的最大token数',
                'data_type': 'integer',
                'value_range': json.dumps({'min': 10, 'max': 100}),
                'is_reload_required': False
            },
            'INDEX_TTS_FAST_BATCH_SIZE': {
                'group': 'model',
                'category': 'tts',
                'display_name': '快速模式批处理大小',
                'description': '快速模式分句分桶的最大容量',
                'data_type': 'integer',
                'value_range': json.dumps({'min': 8, 'max': 128}),
                'is_reload_required': False
            },
            'INDEX_TTS_STREAMING_MIN_SENTENCE_CHARS': {
                'group': 'model',
                'category': 'tts',
                'display_name': '流式模式最小字符数',
                'description': '流式模式最小句子字符数',
                'data_type': 'integer',
                'value_range': json.dumps({'min': 5, 'max': 100}),
                'is_reload_required': False
            },
            'INDEX_TTS_DEVICE': {
                'group': 'model',
                'category': 'tts',
                'display_name': 'IndexTTS设备类型',
                'description': 'IndexTTS-1.5设备类型',
                'data_type': 'string',
                'value_range': json.dumps(['cuda', 'cpu']),
                'is_reload_required': True
            },
            'INDEX_TTS_MAX_WORKERS': {
                'group': 'model',
                'category': 'tts',
                'display_name': 'IndexTTS最大并发数',
                'description': 'IndexTTS-1.5最大并发数',
                'data_type': 'integer',
                'value_range': json.dumps({'min': 1, 'max': 16}),
                'is_reload_required': True
            },
            'INDEX_TTS_TIMEOUT': {
                'group': 'model',
                'category': 'tts',
                'display_name': 'IndexTTS超时时间',
                'description': 'IndexTTS-1.5超时时间（秒）',
                'data_type': 'integer',
                'value_range': json.dumps({'min': 10, 'max': 300}),
                'is_reload_required': False
            },
            'INDEX_TTS_REFERENCE_AUDIO': {
                'group': 'model',
                'category': 'tts',
                'display_name': 'IndexTTS参考音频',
                'description': 'IndexTTS-1.5默认参考音频文件名',
                'data_type': 'string',
                'is_reload_required': False
            },

            # 数据库配置
            'MYSQL_HOST': {
                'group': 'database',
                'category': 'connection',
                'display_name': 'MySQL主机地址',
                'description': 'MySQL数据库服务器地址',
                'data_type': 'string',
                'validation_rule': r'^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$|localhost$',
                'is_reload_required': True
            },
            'MYSQL_PORT': {
                'group': 'database',
                'category': 'connection',
                'display_name': 'MySQL端口',
                'description': 'MySQL数据库服务器端口',
                'data_type': 'integer',
                'value_range': json.dumps({'min': 1, 'max': 65535}),
                'is_reload_required': True
            },
            'MYSQL_USER': {
                'group': 'database',
                'category': 'connection',
                'display_name': 'MySQL用户名',
                'description': 'MySQL数据库用户名',
                'data_type': 'string',
                'is_sensitive': True,
                'is_reload_required': True
            },
            'MYSQL_PASSWORD': {
                'group': 'database',
                'category': 'connection',
                'display_name': 'MySQL密码',
                'description': 'MySQL数据库密码',
                'data_type': 'secret',
                'is_sensitive': True,
                'is_reload_required': True
            },
            'MYSQL_DATABASE': {
                'group': 'database',
                'category': 'connection',
                'display_name': 'MySQL数据库名',
                'description': 'MySQL数据库名称',
                'data_type': 'string',
                'is_reload_required': True
            },

            # 数据库功能配置
            'QUERY_CLEANING': {
                'group': 'database',
                'category': 'feature',
                'display_name': '启用查询清理',
                'description': '是否启用数据库查询清理功能',
                'data_type': 'boolean',
                'is_reload_required': False
            },

            # MySQL连接池配置
            'DB_POOL_ENABLED': {
                'group': 'database',
                'category': 'pool',
                'display_name': '启用连接池',
                'description': '是否启用数据库连接池',
                'data_type': 'boolean',
                'is_reload_required': True
            },
            'DB_POOL_SIZE': {
                'group': 'database',
                'category': 'pool',
                'display_name': '连接池大小',
                'description': '数据库连接池的最大连接数',
                'data_type': 'integer',
                'value_range': json.dumps({'min': 1, 'max': 100}),
                'is_reload_required': True
            },
            'DB_POOL_TIMEOUT': {
                'group': 'database',
                'category': 'pool',
                'display_name': '连接池超时',
                'description': '连接池获取连接超时时间(秒)',
                'data_type': 'integer',
                'value_range': json.dumps({'min': 5, 'max': 300}),
                'is_reload_required': True
            },
            'DB_POOL_RECYCLE': {
                'group': 'database',
                'category': 'pool',
                'display_name': '连接回收时间',
                'description': '连接回收时间(秒)',
                'data_type': 'integer',
                'value_range': json.dumps({'min': 300, 'max': 7200}),
                'is_reload_required': True
            },
            'DB_POOL_PRE_PING': {
                'group': 'database',
                'category': 'pool',
                'display_name': '连接前检查',
                'description': '连接前检查连接有效性',
                'data_type': 'boolean',
                'is_reload_required': True
            },

            # 熔断器配置
            'DB_CIRCUIT_BREAKER_THRESHOLD': {
                'group': 'database',
                'category': 'circuit_breaker',
                'display_name': '熔断器阈值',
                'description': '熔断器失败阈值',
                'data_type': 'integer',
                'value_range': json.dumps({'min': 1, 'max': 20}),
                'is_reload_required': True
            },
            'DB_CIRCUIT_BREAKER_TIMEOUT': {
                'group': 'database',
                'category': 'circuit_breaker',
                'display_name': '熔断器恢复时间',
                'description': '熔断器恢复时间(秒)',
                'data_type': 'integer',
                'value_range': json.dumps({'min': 10, 'max': 600}),
                'is_reload_required': True
            },

            # 重试机制配置
            'DB_RETRY_ENABLED': {
                'group': 'database',
                'category': 'retry',
                'display_name': '启用重试机制',
                'description': '是否启用重试机制',
                'data_type': 'boolean',
                'is_reload_required': True
            },
            'DB_RETRY_MAX_ATTEMPTS': {
                'group': 'database',
                'category': 'retry',
                'display_name': '最大重试次数',
                'description': '最大重试次数',
                'data_type': 'integer',
                'value_range': json.dumps({'min': 0, 'max': 10}),
                'is_reload_required': True
            },
            'DB_RETRY_BACKOFF_FACTOR': {
                'group': 'database',
                'category': 'retry',
                'display_name': '重试退避因子',
                'description': '重试退避因子',
                'data_type': 'float',
                'value_range': json.dumps({'min': 1.0, 'max': 5.0}),
                'is_reload_required': True
            },
            'DB_RETRY_MAX_DELAY': {
                'group': 'database',
                'category': 'retry',
                'display_name': '最大重试延迟',
                'description': '最大重试延迟(秒)',
                'data_type': 'integer',
                'value_range': json.dumps({'min': 1, 'max': 300}),
                'is_reload_required': True
            },

            # SQL数据库配置 (NL2SQL工具)
            'SQL_DB_TYPE': {
                'group': 'database',
                'category': 'sql',
                'display_name': 'SQL数据库类型',
                'description': 'NL2SQL工具使用的数据库类型',
                'data_type': 'string',
                'value_range': json.dumps(['mysql', 'postgresql', 'sqlite']),
                'is_reload_required': False
            },
            'SQL_DB_HOST': {
                'group': 'database',
                'category': 'sql',
                'display_name': 'SQL数据库主机',
                'description': 'NL2SQL工具数据库主机地址',
                'data_type': 'string',
                'is_reload_required': False
            },
            'SQL_DB_PORT': {
                'group': 'database',
                'category': 'sql',
                'display_name': 'SQL数据库端口',
                'description': 'NL2SQL工具数据库端口',
                'data_type': 'integer',
                'value_range': json.dumps({'min': 1, 'max': 65535}),
                'is_reload_required': False
            },
            'SQL_DB_USERNAME': {
                'group': 'database',
                'category': 'sql',
                'display_name': 'SQL数据库用户名',
                'description': 'NL2SQL工具数据库用户名',
                'data_type': 'string',
                'is_sensitive': True,
                'is_reload_required': False
            },
            'SQL_DB_PASSWORD': {
                'group': 'database',
                'category': 'sql',
                'display_name': 'SQL数据库密码',
                'description': 'NL2SQL工具数据库密码',
                'data_type': 'secret',
                'is_sensitive': True,
                'is_reload_required': False
            },
            'SQL_DB_DATABASE': {
                'group': 'database',
                'category': 'sql',
                'display_name': 'SQL数据库名',
                'description': 'NL2SQL工具数据库名称',
                'data_type': 'string',
                'is_reload_required': False
            },

            # 工具系统配置
            'TOOLS_ENABLED': {
                'group': 'tools',
                'category': 'general',
                'display_name': '启用工具系统',
                'description': '工具系统总开关（控制所有工具功能）',
                'data_type': 'boolean',
                'is_reload_required': False
            },
            'NL2SQL_ENABLED': {
                'group': 'tools',
                'category': 'nl2sql',
                'display_name': '启用NL2SQL',
                'description': '是否启用自然语言转SQL查询功能',
                'data_type': 'boolean',
                'is_reload_required': False
            },

            # 时间工具配置
            'TIME_TOOLS_ENABLED': {
                'group': 'tools',
                'category': 'time',
                'display_name': '启用时间工具',
                'description': '是否启用时间工具（支持自然语言时间解析）',
                'data_type': 'boolean',
                'is_reload_required': False
            },
            'TIME_ZONE': {
                'group': 'tools',
                'category': 'time',
                'display_name': '时区设置',
                'description': '系统时区设置',
                'data_type': 'string',
                'placeholder': 'Asia/Shanghai',
                'is_reload_required': False
            },
            'TIME_FORMAT_DEFAULT': {
                'group': 'tools',
                'category': 'time',
                'display_name': '默认时间格式',
                'description': '默认时间格式',
                'data_type': 'string',
                'placeholder': '%Y-%m-%d %H:%M:%S',
                'is_reload_required': False
            },

            # ADB工具配置
            'ADB_TOOLS_ENABLED': {
                'group': 'tools',
                'category': 'adb',
                'display_name': '启用ADB工具',
                'description': '是否启用ADB工具',
                'data_type': 'boolean',
                'is_reload_required': False
            },
            'ADB_COMMAND_PATH': {
                'group': 'tools',
                'category': 'adb',
                'display_name': 'ADB命令路径',
                'description': 'ADB命令路径',
                'data_type': 'path',
                'placeholder': '/mnt/c/platform-tools/adb.exe',
                'is_reload_required': False
            },
            'ADB_TIMEOUT': {
                'group': 'tools',
                'category': 'adb',
                'display_name': 'ADB操作超时时间',
                'description': 'ADB操作超时时间（秒）',
                'data_type': 'integer',
                'value_range': json.dumps({'min': 5, 'max': 300}),
                'is_reload_required': False
            },
            'ADB_RETRY_COUNT': {
                'group': 'tools',
                'category': 'adb',
                'display_name': 'ADB操作重试次数',
                'description': 'ADB操作重试次数',
                'data_type': 'integer',
                'value_range': json.dumps({'min': 0, 'max': 10}),
                'is_reload_required': False
            },

            # 数字人配置
            'ANY4DH_ENABLED': {
                'group': 'digital_human',
                'category': 'general',
                'display_name': '启用数字人',
                'description': '是否启用any4dh数字人',
                'data_type': 'boolean',
                'is_reload_required': True
            },
            'ANY4DH_USE_UNIFIED_INTERFACE': {
                'group': 'digital_human',
                'category': 'general',
                'display_name': '使用统一接口',
                'description': '是否使用统一接口',
                'data_type': 'boolean',
                'is_reload_required': False
            },
            'ANY4DH_TRANSPORT': {
                'group': 'digital_human',
                'category': 'general',
                'display_name': '传输方式',
                'description': '数字人多媒体传输方式',
                'data_type': 'string',
                'value_range': json.dumps(['webrtc', 'rtmp']),
                'is_reload_required': True
            },
            'ANY4DH_MODEL': {
                'group': 'digital_human',
                'category': 'model',
                'display_name': '数字人模型',
                'description': '唇形同步模型',
                'data_type': 'string',
                'value_range': json.dumps(['wav2lip']),
                'is_reload_required': True
            },
            'ANY4DH_AVATAR_ID': {
                'group': 'digital_human',
                'category': 'avatar',
                'display_name': '头像ID',
                'description': '数字人头像ID',
                'data_type': 'string',
                'placeholder': '001',
                'is_reload_required': False
            },
            'ANY4DH_BATCH_SIZE': {
                'group': 'digital_human',
                'category': 'processing',
                'display_name': '批处理大小',
                'description': '模型处理批量处理大小',
                'data_type': 'integer',
                'value_range': json.dumps({'min': 1, 'max': 64}),
                'is_reload_required': False
            },
            'ANY4DH_FPS': {
                'group': 'digital_human',
                'category': 'video',
                'display_name': '视频帧率',
                'description': '视频帧率',
                'data_type': 'integer',
                'value_range': json.dumps({'min': 15, 'max': 60}),
                'is_reload_required': False
            },
            'ANY4DH_TTS': {
                'group': 'digital_human',
                'category': 'tts',
                'display_name': 'TTS模型',
                'description': '唇形同步TTS模型',
                'data_type': 'string',
                'value_range': json.dumps(['edgetts', 'indextts']),
                'is_reload_required': False
            },
            'ANY4DH_REF_FILE': {
                'group': 'digital_human',
                'category': 'tts',
                'display_name': '参考音频文件',
                'description': '唇形同步参考音频文件',
                'data_type': 'string',
                'placeholder': 'zh-CN-YunxiaNeural',
                'is_reload_required': False
            },
            'ANY4DH_REF_TEXT': {
                'group': 'digital_human',
                'category': 'tts',
                'display_name': '参考文本',
                'description': '唇形同步参考文本',
                'data_type': 'string',
                'is_reload_required': False
            },
            'ANY4DH_TTS_SERVER': {
                'group': 'digital_human',
                'category': 'tts',
                'display_name': 'TTS服务地址',
                'description': '唇形同步TTS服务地址',
                'data_type': 'string',
                'placeholder': 'http://127.0.0.1:9880',
                'is_reload_required': False
            },
            'ANY4DH_MAX_SESSION': {
                'group': 'digital_human',
                'category': 'session',
                'display_name': '最大会话数',
                'description': '最大会话数',
                'data_type': 'integer',
                'value_range': json.dumps({'min': 1, 'max': 10}),
                'is_reload_required': True
            },
            'ANY4DH_AVATARS_DIR': {
                'group': 'digital_human',
                'category': 'avatar',
                'display_name': '头像目录',
                'description': 'any4dh人物模型目录',
                'data_type': 'path',
                'placeholder': 'data/avatars',
                'is_reload_required': True
            },

            # 语音知识库配置
            'ANY4DH_VOICE_KB_ENABLED': {
                'group': 'digital_human',
                'category': 'voice_kb',
                'display_name': '启用语音知识库',
                'description': '是否启用语音知识库',
                'data_type': 'boolean',
                'is_reload_required': False
            },
            'ANY4DH_VOICE_KB_LANGUAGE': {
                'group': 'digital_human',
                'category': 'voice_kb',
                'display_name': '语音知识库语言',
                'description': '语音知识库语言',
                'data_type': 'string',
                'value_range': json.dumps(['zh', 'en']),
                'is_reload_required': False
            },
            'ANY4DH_VOICE_KB_FALLBACK_TO_TTS': {
                'group': 'digital_human',
                'category': 'voice_kb',
                'display_name': '回退到TTS',
                'description': '是否在未找到匹配时回退到TTS',
                'data_type': 'boolean',
                'is_reload_required': False
            },
            'ANY4DH_VOICE_KB_SEMANTIC_THRESHOLD': {
                'group': 'digital_human',
                'category': 'voice_kb',
                'display_name': '语义匹配阈值',
                'description': '语音语义匹配阈值（低于此值使用LLM生成）',
                'data_type': 'float',
                'value_range': json.dumps({'min': 0.0, 'max': 1.0}),
                'is_reload_required': False
            },
            'VOICE_KB_CSV_PATH': {
                'group': 'digital_human',
                'category': 'voice_kb',
                'display_name': '语音知识库CSV路径',
                'description': '语音知识库CSV文件路径',
                'data_type': 'path',
                'placeholder': 'data/csv/en_voice_list.csv',
                'is_reload_required': False
            },
            'VOICE_KB_AUDIO_DIR': {
                'group': 'digital_human',
                'category': 'voice_kb',
                'display_name': '语音知识库音频目录',
                'description': '语音知识库音频文件目录',
                'data_type': 'path',
                'placeholder': 'data/en_answer',
                'is_reload_required': False
            },

            # 钉钉配置
            'DINGTALK_ENABLED': {
                'group': 'external',
                'category': 'dingtalk',
                'display_name': '启用钉钉机器人',
                'description': '是否启用钉钉机器人服务',
                'data_type': 'boolean',
                'is_reload_required': True
            },
            'CLIENT_ID': {
                'group': 'external',
                'category': 'dingtalk',
                'display_name': '钉钉客户端ID',
                'description': '钉钉机器人客户端ID',
                'data_type': 'string',
                'is_sensitive': True,
                'is_reload_required': False
            },
            'CLIENT_SECRET': {
                'group': 'external',
                'category': 'dingtalk',
                'display_name': '钉钉客户端密钥',
                'description': '钉钉机器人客户端密钥',
                'data_type': 'secret',
                'is_sensitive': True,
                'is_reload_required': False
            },
            'ROBOT_CODE': {
                'group': 'external',
                'category': 'dingtalk',
                'display_name': '钉钉机器人密钥',
                'description': '钉钉机器人机器人密钥',
                'data_type': 'string',
                'is_sensitive': True,
                'is_reload_required': False
            },
            'DINGTALK_PORT': {
                'group': 'external',
                'category': 'dingtalk',
                'display_name': '钉钉机器人端口',
                'description': '钉钉机器人服务端口号',
                'data_type': 'integer',
                'value_range': json.dumps({'min': 1024, 'max': 65535}),
                'is_reload_required': True
            },

            # Web搜索工具配置
            'WEB_SEARCH_ENABLED': {
                'group': 'external',
                'category': 'web_search',
                'display_name': '启用Web搜索',
                'description': '是否启用Web搜索工具',
                'data_type': 'boolean',
                'is_reload_required': False
            },
            'WEB_SEARCH_PROXY_URL': {
                'group': 'external',
                'category': 'web_search',
                'display_name': 'Web搜索代理URL',
                'description': 'Web搜索代理URL（可选）',
                'data_type': 'string',
                'validation_rule': r'^https?://[^\s/$.?#].[^\s]*$',
                'is_reload_required': False
            },
            'WEB_SEARCH_USE_PROXY': {
                'group': 'external',
                'category': 'web_search',
                'display_name': '使用代理搜索',
                'description': '是否使用代理进行Web搜索',
                'data_type': 'boolean',
                'is_reload_required': False
            },
            'WEB_SEARCH_RESULT_LIMIT': {
                'group': 'external',
                'category': 'web_search',
                'display_name': '搜索结果限制',
                'description': 'Web搜索结果数量限制',
                'data_type': 'integer',
                'value_range': json.dumps({'min': 5, 'max': 50}),
                'is_reload_required': False
            },
            'WEB_SEARCH_TIMEOUT': {
                'group': 'external',
                'category': 'web_search',
                'display_name': '搜索超时时间',
                'description': 'Web搜索请求超时时间(秒)',
                'data_type': 'integer',
                'value_range': json.dumps({'min': 5, 'max': 120}),
                'is_reload_required': False
            },
            'WEB_SEARCH_RATE_LIMIT': {
                'group': 'external',
                'category': 'web_search',
                'display_name': '搜索频率限制',
                'description': 'Web搜索频率限制(每分钟最多搜索次数)',
                'data_type': 'integer',
                'value_range': json.dumps({'min': 1, 'max': 60}),
                'is_reload_required': False
            },
            'WEB_SEARCH_PRIMARY_ENGINE': {
                'group': 'external',
                'category': 'web_search',
                'display_name': '主搜索引擎',
                'description': '主搜索引擎',
                'data_type': 'string',
                'value_range': json.dumps(['bing', 'duckduckgo', 'google']),
                'is_reload_required': False
            },
            'WEB_SEARCH_FALLBACK_ENGINES': {
                'group': 'external',
                'category': 'web_search',
                'display_name': '备用搜索引擎',
                'description': '备用搜索引擎（逗号分隔）',
                'data_type': 'string',
                'is_reload_required': False
            },
            'WEB_SEARCH_MAX_RETRIES': {
                'group': 'external',
                'category': 'web_search',
                'display_name': '搜索最大重试次数',
                'description': '搜索失败最大重试次数',
                'data_type': 'integer',
                'value_range': json.dumps({'min': 0, 'max': 10}),
                'is_reload_required': False
            },
            'WEB_SEARCH_RETRY_DELAY': {
                'group': 'external',
                'category': 'web_search',
                'display_name': '搜索重试延迟时间',
                'description': '重试延迟时间(秒)',
                'data_type': 'float',
                'value_range': json.dumps({'min': 0.1, 'max': 10.0}),
                'is_reload_required': False
            }
        }

    def _get_group_display_name(self, group_name: str) -> str:
        """获取分组显示名称"""
        display_names = {
            'server': '服务器配置',
            'auth': '认证与会话',
            'model': '模型配置',
            'database': '数据库配置',
            'tools': '工具系统',
            'digital_human': '数字人配置',
            'external': '外部服务',
            'advanced': '高级配置'
        }
        return display_names.get(group_name, group_name)

    def _get_group_description(self, group_name: str) -> str:
        """获取分组描述"""
        descriptions = {
            'server': '基础服务器设置和端口配置',
            'auth': 'API认证和会话管理配置',
            'model': 'AI模型路径和参数配置',
            'database': 'MySQL数据库连接和高级配置',
            'tools': '各种工具功能的开关和参数',
            'digital_human': 'Any4DH数字人相关配置',
            'external': '第三方服务集成配置',
            'advanced': '系统级高级配置选项'
        }
        return descriptions.get(group_name, f'{group_name}相关配置')

    def _get_group_icon(self, group_name: str) -> str:
        """获取分组图标"""
        icons = {
            'server': 'layui-icon-set',
            'auth': 'layui-icon-password',
            'model': 'layui-icon-chart',
            'database': 'layui-icon-table',
            'tools': 'layui-icon-tool',
            'digital_human': 'layui-icon-face-smile',
            'external': 'layui-icon-link',
            'advanced': 'layui-icon-set-fill'
        }
        return icons.get(group_name, 'layui-icon-app')

    async def import_from_env(self, env_file: str = '.env') -> Dict[str, Any]:
        """
        从 .env 文件导入配置到数据库

        Args:
            env_file: .env文件路径

        Returns:
            Dict[str, Any]: 导入结果统计
        """
        # 1. 加载环境变量
        env_path = project_root / env_file
        if not env_path.exists():
            raise FileNotFoundError(f"Environment file not found: {env_path}")

        load_dotenv(env_path)
        logger.info(f"Loaded environment variables from {env_file}")

        # 2. 获取数据库配置并初始化配置管理器
        db_config = {
            'host': os.getenv('MYSQL_HOST', 'localhost'),
            'port': int(os.getenv('MYSQL_PORT', 3306)),
            'user': os.getenv('MYSQL_USER', 'root'),
            'password': os.getenv('MYSQL_PASSWORD', 'root'),
            'database': os.getenv('MYSQL_DATABASE', 'any4any')
        }

        config_manager = ConfigManager(db_config)

        try:
            # 初始化配置管理器
            if not await config_manager.initialize():
                raise Exception("Failed to initialize config manager")

            logger.info("Config manager initialized successfully")

            # 3. 执行导入
            result = await self._perform_import(config_manager)

            return result

        finally:
            await config_manager.close()

    async def _perform_import(self, config_manager: ConfigManager) -> Dict[str, Any]:
        """执行配置导入"""
        result = {
            'total_configs': 0,
            'imported_configs': 0,
            'skipped_configs': 0,
            'error_configs': 0,
            'errors': []
        }

        try:
            # 4. 创建配置分组
            groups_created = await self._create_config_groups(config_manager)
            logger.info(f"Created {groups_created} config groups")

            # 5. 导入配置项
            for key, mapping in self.config_mappings.items():
                result['total_configs'] += 1

                try:
                    env_value = os.getenv(key)
                    if env_value is None:
                        logger.warning(f"Environment variable {key} not found, skipping")
                        result['skipped_configs'] += 1
                        continue

                    # 获取分组ID
                    group_id = await self._get_group_id(config_manager, mapping['group'])
                    if not group_id:
                        logger.warning(f"Group {mapping['group']} not found for key {key}")
                        result['error_configs'] += 1
                        result['errors'].append(f"Group {mapping['group']} not found for key {key}")
                        continue

                    # 检查配置项是否已存在
                    existing_item = await config_manager._repository.get_config_item_by_key(key)
                    if existing_item:
                        logger.info(f"Config item {key} already exists, updating current value")
                        # 更新当前值
                        await config_manager._repository.update_config_value(key, env_value)
                        result['imported_configs'] += 1
                    else:
                        # 创建新配置项
                        item_data = {
                            'group_id': group_id,
                            'category': mapping['category'],
                            'key_name': key,
                            'display_name': mapping['display_name'],
                            'description': mapping.get('description'),
                            'data_type': mapping['data_type'],
                            'default_value': env_value,
                            'current_value': env_value,
                            'value_range': mapping.get('value_range'),
                            'validation_rule': mapping.get('validation_rule'),
                            'is_sensitive': mapping.get('is_sensitive', False),
                            'is_reload_required': mapping.get('is_reload_required', True),
                            'is_readonly': mapping.get('is_readonly', False),
                            'placeholder': mapping.get('placeholder'),
                            'sort_order': result['total_configs']
                        }

                        await config_manager._repository.create_config_item(item_data)
                        logger.info(f"Created config item: {key}")
                        result['imported_configs'] += 1

                    self.processed_keys.add(key)

                except Exception as e:
                    logger.error(f"Failed to import config {key}: {e}")
                    result['error_configs'] += 1
                    result['errors'].append(f"Failed to import {key}: {str(e)}")

            logger.info(f"Config import completed: {result}")

        except Exception as e:
            logger.error(f"Config import failed: {e}")
            result['errors'].append(f"Import failed: {str(e)}")

        return result

    async def _create_config_groups(self, config_manager: ConfigManager) -> int:
        """创建配置分组"""
        groups = {}
        sort_order = 1

        for key, mapping in self.config_mappings.items():
            group_name = mapping['group']
            if group_name not in groups:
                groups[group_name] = {
                    'name': group_name,
                    'display_name': self._get_group_display_name(group_name),
                    'description': self._get_group_description(group_name),
                    'icon': self._get_group_icon(group_name),
                    'sort_order': sort_order
                }
                sort_order += 1

        created_count = 0
        for group_data in groups.values():
            try:
                # 检查分组是否已存在
                existing_group = await config_manager._repository.get_config_group_by_name(group_data['name'])
                if existing_group:
                    logger.info(f"Group {group_data['name']} already exists, skipping")
                    continue

                await config_manager._repository.create_config_group(group_data)
                logger.info(f"Created config group: {group_data['name']}")
                created_count += 1
            except Exception as e:
                logger.error(f"Failed to create group {group_data['name']}: {e}")

        return created_count

    async def _get_group_id(self, config_manager: ConfigManager, group_name: str) -> Optional[int]:
        """获取分组ID"""
        try:
            group = await config_manager._repository.get_config_group_by_name(group_name)
            return group['id'] if group else None
        except Exception:
            return None


async def main():
    """主函数"""
    import argparse

    parser = argparse.ArgumentParser(description='Import configuration from .env file to database')
    parser.add_argument('--env-file', default='.env', help='Path to .env file')
    parser.add_argument('--dry-run', action='store_true', help='Dry run (do not actually import)')

    args = parser.parse_args()

    try:
        importer = ConfigImporter()

        if args.dry_run:
            logger.info("Dry run mode - checking environment variables...")
            load_dotenv(args.env_file)

            for key in importer.config_mappings.keys():
                value = os.getenv(key)
                if value is not None:
                    logger.info(f"Found: {key}={value}")
                else:
                    logger.warning(f"Not found: {key}")

            logger.info(f"Total config keys defined: {len(importer.config_mappings)}")
            return

        # 执行导入
        result = await importer.import_from_env(args.env_file)

        # 打印结果
        print("\n" + "="*50)
        print("配置导入完成")
        print("="*50)
        print(f"总配置项数量: {result['total_configs']}")
        print(f"成功导入: {result['imported_configs']}")
        print(f"跳过配置: {result['skipped_configs']}")
        print(f"错误配置: {result['error_configs']}")

        if result['errors']:
            print("\n错误详情:")
            for error in result['errors']:
                print(f"  - {error}")

        print("="*50)

        if result['error_configs'] == 0:
            logger.info("Configuration import completed successfully!")
            return 0
        else:
            logger.warning(f"Configuration import completed with {result['error_configs']} errors")
            return 1

    except Exception as e:
        logger.error(f"Import failed: {e}")
        return 1


if __name__ == '__main__':
    import sys
    sys.exit(asyncio.run(main()))